package cz.muni.fi.pv112.cranesimulator.utils;

import cz.muni.fi.pv112.cranesimulator.scene.Scene;
import cz.muni.fi.pv112.cranesimulator.scene.items.CameraInterface;
import static java.lang.Math.cos;
import static java.lang.Math.sin;
import static java.lang.Math.toRadians;

/**
 *
 * @author Michal Ďuriš
 */
public class Calculator {

    private static final float[] orientationStorageField = {0.0f, 0.0f, 0.0f};

    public static float[] moveBy(float moveX, float moveY, float moveZ,
                                 float[] position, float[] orientation) {
        float[] displacement = recalculateCoordinatesToSceneCoordinateSystem(
                moveX,
                moveY,
                moveZ,
                orientation);

        displacement[Scene.X_AXIS] = position[Scene.X_AXIS]
                + displacement[Scene.X_AXIS];
        displacement[Scene.Y_AXIS] = position[Scene.Y_AXIS]
                + displacement[Scene.Y_AXIS];
        displacement[Scene.Z_AXIS] = position[Scene.Z_AXIS]
                + displacement[Scene.Z_AXIS];

        return displacement;
    }

    public static void rotateAndRecalculateStaticCameraPosition(float angleY,
                                                                CameraInterface camera) {
        orientationStorageField[Scene.Y_AXIS] = angleY;

        camera.setOrientation(camera.getOrientationAngleX(),
                (camera.getOrientationAngleY() + angleY) % 360,
                camera.getOrientationAngleZ());

        camera.setPosition(recalculateCoordinatesToSceneCoordinateSystem(camera
                .getPositionX(),
                camera
                .getPositionY(),
                camera
                .getPositionZ(),
                orientationStorageField));

        orientationStorageField[Scene.Y_AXIS] = 0.0f;
    }

    public static float[] recalculateCoordinatesToSceneCoordinateSystem(float dx,
                                                                        float dy,
                                                                        float dz,
                                                                        float[] orientation) {
        float[] coordinates = new float[3];

        if (dx == 0 && dy == 0 && dz == 0) {
            return coordinates;
        }

        double xRotation = toRadians(orientation[Scene.X_AXIS]);
        double yRotation = toRadians(orientation[Scene.Y_AXIS]);

        coordinates[Scene.X_AXIS] = (float) (dx * cos(yRotation) + dy * sin(
                xRotation) * sin(yRotation) - dz * cos(xRotation) * sin(
                        yRotation));
        coordinates[Scene.Y_AXIS] = (float) (dy * cos(xRotation) + dz * sin(
                xRotation));
        coordinates[Scene.Z_AXIS] = (float) (dx * sin(yRotation) - dy * sin(
                xRotation) * cos(yRotation) + dz * cos(xRotation) * cos(
                        yRotation));

        return coordinates;
    }

}
